;; 自定义快捷键绑定，对Emacs快捷键的修改和增强

;; key-translation-map，优先级最高
;; (define-key key-translation-map (kbd "your-key") (kbd "target-key"))
;; minor-mode-map，优先级第二
;; (define-key some-minor-mode-map (kbd "your-key") 'your-command)
;; local-set-key，优先级第三
;; (local-set-key (kbd "your-key") 'your-command)
;; global-set-key，优先级最低
;; (global-set-key (kbd "your-key") 'your-command)
;; 注销方式：绑定为nil，或者
;; (global-unset-key (kbd "your-key")

(require 'my/extensions)
(require 'my/unicode)
(require 'my/coderunner)

(global-unset-key (kbd "C-SPC"))
(global-unset-key (kbd "C-z"))
(global-set-key (kbd "C-z") 'undo)
(global-set-key (kbd "C-S-z") 'undo-redo)

(global-unset-key (kbd "C-a"))
(global-set-key (kbd "C-a") 'my/smart-beginning-of-line)
(global-set-key [home]      'my/smart-beginning-of-line)
(global-set-key (kbd "C-S-l") (kbd "<end> S-<home>"))

;; key-translation-map 优先级最高，可防止快捷键被覆盖，但只能绑定到其它快捷键
;;(define-key key-translation-map (kbd "C-a") (kbd "C-x h"))
;;(global-set-key (kbd "C-h") (kbd "<home>")) ; 帮助键使用 <f1>

(global-set-key (kbd "M-p") 'scroll-down)
(
 global-set-key (kbd "M-n") 'scroll-up)

(global-set-key (kbd "M-_") (lambda ()
                              "将当前行和下一行连接，对应原生 M-^ 连接到上一行"
                              (interactive) (join-line t)))

;;(global-set-key (kbd "<f2>") 'speedbar)
(global-set-key (kbd "<f4>") 'my/kill-current-buffer)
(defun my/kill-current-buffer ()
  (interactive)
  (kill-buffer (current-buffer)))

;; 窗口相关的操作绑定
(define-key key-translation-map (kbd "M-0") (kbd "C-x 0"))
(define-key key-translation-map (kbd "M-1") (kbd "C-x 1"))
(define-key key-translation-map (kbd "M-2") (kbd "C-x 2"))
(define-key key-translation-map (kbd "M-3") (kbd "C-x 3"))

(global-set-key (kbd "M-o") 'other-window)
(global-set-key (kbd "M-C-0") (lambda ()
                                "关闭当前Buffer并关闭当前Window"
                                (interactive)
                                (unless (buffer-modified-p) (save-buffer))
                                (kill-buffer (current-buffer))
                                (delete-window)))

(global-unset-key (kbd "M-w"))
(global-set-key (kbd "M-w")   'my/copy-line-or-region)

(global-set-key (kbd "C-x C-b") 'ibuffer)

;; 由于 key-translation-map 不支持键盘宏，放弃这里的配置
;; 具体设置在文件尾部
;; (fset 'macro-insert-up-newline (kbd "<home><return><up><tab>"))
;; (fset 'macro-insert-down-newline (kbd "<end><return>"))
;; (global-set-key (kbd "C-S-<return>") 'macro-insert-up-newline)
;; (global-set-key (kbd "C-<return>")   'macro-insert-down-newline)

(fset 'macro-insert-semicolon "\C-e\;")
(global-set-key (kbd "C-;") 'macro-insert-semicolon)

(global-set-key (kbd "M-<backspace>") 'backward-kill-word)
(global-set-key (kbd "M-<delete>")    'kill-word)
(global-set-key (kbd "C-<backspace>") 'my/subword-delete-block-backward)
(global-set-key (kbd "C-<delete>")    'my/subword-delete-block-forward)
(global-set-key (kbd "M-d")           'my/subword-delete-block-forward)

;; (setq my-keymap (make-sparse-keymap))
(define-prefix-command 'my-leader-key)
(global-unset-key (kbd "C-k"))
(global-set-key (kbd "C-k") 'my-leader-key)

(global-set-key (kbd "C-S-k") 'kill-line)
(define-key my-leader-key "\C-k" 'kill-line)

;; Emacs 自带插件，按指定符号对齐
(define-key my-leader-key "=" 'align-regexp)
;; my-leader-key + 空格定义标记开始
(define-key my-leader-key " " 'set-mark-command)
(define-key my-leader-key "o" 'find-file)
(define-key my-leader-key (kbd "b") 'ibuffer)
(define-key my-leader-key (kbd "w") 'my/kill-current-buffer)

;; 代码折叠快捷键设置
(define-key my-leader-key (kbd "<tab>") 'hs-toggle-hiding)
(define-key my-leader-key "H" 'hs-hide-all)
(define-key my-leader-key "S" 'hs-show-all)

(define-key my-leader-key "fi" 'my/find-user-init-file)
(define-key my-leader-key "fu" 'my/find-user-custom-file)
(define-key my-leader-key "fn" 'my/new-empty-buffer)
(define-key my-leader-key "fr" 'my/rename-file-and-buffer)
(define-key my-leader-key "fd" 'my/delete-file-and-buffer)
(define-key my-leader-key "ff" 'my/recentf-find-file)
(define-key my-leader-key "\C-f" 'my/recentf-find-file)
(define-key my-leader-key "fm" 'recentf-open-files)
;; 删除行尾空格和文件尾的多余空行
(define-key my-leader-key "fs" 'delete-trailing-whitespace)
(define-key my-leader-key "fl" 'my/rename-file-and-buffer)

(defun my/recovery-desktop-layout ()
  (interactive)
  (let ((desktop-load-locked-desktop "ask"))
    (desktop-read)
    (desktop-save-mode 1)))

(define-key my-leader-key "id" 'my/insert-date-and-time)
;; Insert unicode symbol and emoji cahr
(define-key my-leader-key "ie" 'emoji-insert)
(define-key my-leader-key "ir" 'emoji-recent)
(define-key my-leader-key "is" 'isearch-emoji-by-name)

;;这样定义是为了防止C-<return> 和 C-S-<return>被覆盖
(define-key my-leader-key "io" 'my/insert-down-newline)
(define-key my-leader-key "iO" 'my/insert-up-newline)
(define-key key-translation-map (kbd "C-<return>") (kbd "C-k i o"))
(define-key key-translation-map (kbd "C-S-<return>") (kbd "C-k i O"))

(global-set-key (kbd "<f5>") 'my/run-current-buffer)
(define-key my-leader-key "\C-c" 'my/run-current-buffer)

;; cua-mode keybind
(custom-set-variables '(cua-rectangle-mark-key [C-M-return]))
;; cua-mode 列操作
;; 插入字符： 直接输入字符即可。会在每行前(或后)都插入这个字符。取决于鼠标在前还是在后。如果需要在前面输入，可以从右下往左上选取区域，或者按回车确认矩形范围以后再移动鼠标。
;; M-b: 用空格(tabs或者spaces)替换所有rect中的字符
;; M-c: 去掉所有行左侧的空格
;; M-f: (fill)用单个字符填充rect(提示输入一个字符)
;; M-i: 对每行中第一个找到的数字进行加1操作(自动把0x开头的当作十六进制数字)
;; M-k: 剪切rect
;; M-m: 拷贝rect
;; M-n: 用一串自增的数字替换rect中的每一行(这个功能可以用来给每行编号)
;; M-o: rect的内容右移，选中的rect用空格填充
;; M-r: 用字符串替换符满足正则表达式的字符串
;; M-R: 上下反转
;; M-s: 把rect中的每一行替换为一个字符串(提示输入)
;; M-t: 把rect整个替换为一个字符串(提示输入)
;; M-l: 把rect中的内容全部转换为小写
;; M-u: 把rect中的内容全部转换为大写
;; C-c: 复制rect
;; C-v: 粘贴rect
;; C-x: 剪切rect
;; C-z: undo
;; M-|: 对rect执行一个shell命令

;; flymake key bind
(add-hook 'flymake-mode-hook
          (lambda ()
            (define-key flymake-mode-map (kbd "C-, C-s") 'flymake-start)
            (define-key flymake-mode-map (kbd "C-, C-l") 'flymake-show-buffer-diagnostics)
            (define-key flymake-mode-map (kbd "C-, C-n") 'flymake-goto-next-error)
            (define-key flymake-mode-map (kbd "C-, C-p") 'flymake-goto-prev-error)
            ))

(provide 'init-keybind)
;;; init-keybind.el ends here
